/**
 * 
 */
package com.fnic.pearl.scheduler.mod;

import java.io.IOException;
import java.util.concurrent.LinkedBlockingDeque;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.log4j.Logger;

import com.fnic.pearl.scheduler.SchedulerConfig;
import com.fnic.pearl.scheduler.constant.CondHeaderField;

/**
 * 该线程主要维护主动发起业务请求至管理节点，如：
 * 
 * - 上报探针节点的测试任务执行状态
 * 
 * @author HuHaiyang
 * @date 2013年7月16日
 */
public class ActiveToManager implements Runnable {

	private static Logger LOG = Logger.getLogger(ActiveToManager.class);

	private DefaultHttpClient client = new DefaultHttpClient();

	private static ActiveToManager instance = new ActiveToManager();
	/**
	 * 需要发送至管理节点的 请求消息 队列， 其中的消息都为 请求消息(HttpUriRequest) 因为当前主要支持 GET, POST 方法，
	 * 且在通信层是需要使用 HttpClient.execute(HttpUriRequest) 方法来发送请求的
	 */
	private static LinkedBlockingDeque<HttpRequestBase> requestQueue = new LinkedBlockingDeque<HttpRequestBase>();

	public static ActiveToManager getInstance() {
		return instance;
	}

	public ActiveToManager() {
		HttpParams params = client.getParams();
		HttpConnectionParams.setConnectionTimeout(params,
				(int) SchedulerConfig.getInstance().getManagerTimeout() * 1000);
		HttpConnectionParams.setSoTimeout(params, (int) SchedulerConfig.getInstance().getManagerTimeout() * 1000);
	}

	/**
	 * 新增 请求消息
	 */
	public void putRequest(HttpRequestBase request) {
		try {
			requestQueue.put(request);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private boolean stop = false;

	public void run() {
		LOG.info("start ATM ...");
		while (!stop) {
			if (!AuthManager.getInstance().loginManager(SchedulerConfig.getInstance().getManagerIp(),
					SchedulerConfig.getInstance().getManagerPort())) {
				try {
					Thread.sleep(SchedulerConfig.getInstance().getManagerTimeout() * 1000);
				} catch (InterruptedException e1) {
					LOG.warn("login manager failed - " + e1.getMessage());
					continue;
				}
			}

			// 从请求队列中查看是否存在未发送的请求
			HttpRequestBase request = null;
			try {
				request = requestQueue.take();
			} catch (InterruptedException e1) {
				LOG.warn("ATM - take request exception: " + e1.getMessage());
				continue;
			}

			if (request != null) {
				String sessionId = AuthManager.getInstance().getSessionIdWithManager();
				if (sessionId == null) {
					LOG.info("there is no cookie, will wait to login succ.");
					requestQueue.addFirst(request);
				} else {
					request.addHeader(CondHeaderField.HEADER_COOKIE, CondHeaderField.SESSION_ID + "=" + sessionId);
					LOG.info("send request - " + request.getRequestLine() + "|session:" + sessionId);
					try {
						HttpResponse response = client.execute(request);

						// TODO 需要在此解析 Manager 的响应消息
						// 并需要将响应解码，并递送至上层队列

						LOG.info("resp status line: " + response.getStatusLine());
					} catch (ClientProtocolException e) {
						LOG.error("protocol is ex: " + e.getMessage());
					} catch (IOException e) {
						LOG.error("Maybe connection was aborted: " + e.getMessage());
						// AuthManager.getInstance().isLoginManager(false);
						AuthManager.getInstance().countDown();
						requestQueue.addFirst(request);
					} catch (Exception e) {
						LOG.error("other exception: " + e.getMessage());
					}
				}

				request.releaseConnection();
			}
		}

		client.getConnectionManager().shutdown();
	}

	/**
	 * 发送指定的 request，并返回 http response
	 * 
	 * @param request
	 *            待发送的请求
	 * @return 0 成功 -1 输入参数非法 -2 protocal exception -3 IO exception
	 */
	// public HttpResponse sendRequest(HttpRequestBase request) {
	// try {
	// if (request == null) {
	// LOG.warn("send request - invalid param.");
	// return null;
	// }
	//
	// String sessionId = AuthManager.getInstance().getSessionIdWithManager();
	// if (sessionId == null) {
	// LOG.info("there is no cookie, will wait to login succ.");
	// return null;
	// }
	// DefaultHttpClient client = new DefaultHttpClient();
	// request.addHeader(CondHeaderField.HEADER_COOKIE,
	// CondHeaderField.SESSION_ID + "=" + sessionId);
	// LOG.info("probeLogin请求msgdriver： " + request.getRequestLine());
	// // 设置超时
	// HttpParams params = client.getParams();
	// HttpConnectionParams.setConnectionTimeout(params, (int) 10 * 1000);
	// HttpConnectionParams.setSoTimeout(params, 10 * 1000);
	// HttpResponse response = client.execute(request);
	// LOG.info("resp status line: " + response.getStatusLine());
	// return response;
	// } catch (ClientProtocolException e) {
	// LOG.error("protocol is ex: " + e.getMessage());
	// return null;
	// } catch (IOException e) {
	// LOG.error("Maybe connection was aborted: " + e.getMessage());
	// return null;
	// } finally {
	// // 关闭连接.
	// client.getConnectionManager().shutdown();
	// }
	// }
}
